"use strict";

var HmacSHA1 = require('hmacsha1');
// var CryptoJS = require("crypto-js");

var QiniuApp = {
    Bucket: "qtestbucket",
    //qiniu test account
    AK: "iN7NgwM31j4-BZacMjPrOQBs34UG1maYCAQmhdCV",
    SK: "6QTOr2Jg1gcZEWDQXKOGZh5PziC2MCV5KsntT70j"
};

var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
var Base = {
    utf16to8: function utf16to8(str) {
        var out, i, len, c;
        out = "";
        len = str.length;
        for (i = 0; i < len; i++) {
            c = str.charCodeAt(i);
            if (c >= 0x0001 && c <= 0x007F) {
                out += str.charAt(i);
            } else if (c > 0x07FF) {
                out += String.fromCharCode(0xE0 | c >> 12 & 0x0F);
                out += String.fromCharCode(0x80 | c >> 6 & 0x3F);
                out += String.fromCharCode(0x80 | c >> 0 & 0x3F);
            } else {
                out += String.fromCharCode(0xC0 | c >> 6 & 0x1F);
                out += String.fromCharCode(0x80 | c >> 0 & 0x3F);
            }
        }
        return out;
    },
    utf8to16: function utf8to16(str) {
        var out, i, len, c;
        var char2, char3;
        out = "";
        len = str.length;
        i = 0;
        while (i < len) {
            c = str.charCodeAt(i++);
            switch (c >> 4) {
                case 0:
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                case 7:
                    // 0xxxxxxx
                    out += str.charAt(i - 1);
                    break;
                case 12:
                case 13:
                    // 110x xxxx 10xx xxxx
                    char2 = str.charCodeAt(i++);
                    out += String.fromCharCode((c & 0x1F) << 6 | char2 & 0x3F);
                    break;
                case 14:
                    // 1110 xxxx 10xx xxxx 10xx xxxx
                    char2 = str.charCodeAt(i++);
                    char3 = str.charCodeAt(i++);
                    out += String.fromCharCode((c & 0x0F) << 12 | (char2 & 0x3F) << 6 | (char3 & 0x3F) << 0);
                    break;
            }
        }
        return out;
    },
    base64encode: function base64encode(str) {
        var out, i, len;
        var c1, c2, c3;
        len = str.length;
        i = 0;
        out = "";
        while (i < len) {
            c1 = str.charCodeAt(i++) & 0xff;
            if (i == len) {
                out += base64EncodeChars.charAt(c1 >> 2);
                out += base64EncodeChars.charAt((c1 & 0x3) << 4);
                out += "==";
                break;
            }
            c2 = str.charCodeAt(i++);
            if (i == len) {
                out += base64EncodeChars.charAt(c1 >> 2);
                out += base64EncodeChars.charAt((c1 & 0x3) << 4 | (c2 & 0xF0) >> 4);
                out += base64EncodeChars.charAt((c2 & 0xF) << 2);
                out += "=";
                break;
            }
            c3 = str.charCodeAt(i++);
            out += base64EncodeChars.charAt(c1 >> 2);
            out += base64EncodeChars.charAt((c1 & 0x3) << 4 | (c2 & 0xF0) >> 4);
            out += base64EncodeChars.charAt((c2 & 0xF) << 2 | (c3 & 0xC0) >> 6);
            out += base64EncodeChars.charAt(c3 & 0x3F);
        }
        return out;
    },
    safe64: function safe64(base64) {
        base64 = base64.replace(/\+/g, "-");
        base64 = base64.replace(/\//g, "_");
        return base64;
    }
};

var QiniuUtils = {
    genPutPolicy: function genPutPolicy(bucket, key, deadline, returnBody) {
        return {
            "scope": key ? bucket : bucket + ":" + key,
            "deadline": deadline ? deadline : new Date().valueOf() + 3600 * 24,
            "returnBody": returnBody ? returnBody : '{"key": $(key), "hash": $(etag), "w": $(imageInfo.width), "h": $(imageInfo.height)}'
        };
    },
    genToken: function genToken(accessKey, secretKey, putPolicy) {
        //SETP 2
        var put_policy = JSON.stringify(putPolicy);
        // console.log("put_policy = ", put_policy);
        //SETP 3
        var encoded = Base.base64encode(Base.utf16to8(put_policy));
        // console.log("encoded = ", encoded);
        //SETP 4
        var encoded_signed = HmacSHA1(secretKey, encoded);
        //        var hash = CryptoJS.HmacSHA1(encoded, secretKey);
        //        var encoded_signed = hash.toString(CryptoJS.enc.Base64);
        // console.log("encoded_signed = ", encoded_signed);
        //SETP 5
        var upload_token = accessKey + ":" + Base.safe64(encoded_signed) + ":" + encoded;
        // console.log("upload_token = ", upload_token);
        return upload_token;
    },
    genUploadToken: function genUploadToken(Key, App) {
        var App = App ? App : QiniuApp;
        return QiniuUtils.genToken(App.AK, App.SK, QiniuUtils.genPutPolicy(App.Bucket, Key));
    }
};

module.exports = {
    Utils: QiniuUtils
};